package service

import (
	"core/auth"
	"core/coreentity"
	"core/coreqto"
	"core/coreservice"
	"core/corestruct"
	"core/coreutil"
	"core/datetime"
	"core/myerrors"
	"gorm.io/gorm"
	"ht/api/htrole/data"
	"strconv"
)

type mainService struct {
}

// Page 按机构用户分页
func (p *mainService) Page(mm *coreqto.BasePageQto, ctx *corestruct.HttpContext) (*corestruct.Page[data.HtRoleDto], error) {
	var db = ctx.DB
	tx := db.Model(&coreentity.HtRole{}).
		Select("HtRole.*,ur.Name as crt_uname,dt.name as crt_dname,pt.name as htplat_name").
		Joins("inner join htuser ur on   HtRole.crt_uid=ur.id", "").
		Joins("inner join htdept dt on HtRole.crt_did=dt.id", "").
		Joins("inner join htplat pt on HtRole.htplat_id=pt.id", "")
	if mm.Id > 0 {
		tx = tx.Where("HtRole.id=?", mm.Id)
	} else {
		if "" != mm.Key {
			var keyValue = "%" + mm.Key + "%"
			tx = tx.Where("HtRole.name like ? or HtRole.memo like ?", keyValue, keyValue)
		}
	}
	var svr = &coreservice.PageService[data.HtRoleDto]{}
	r, err := svr.Page(mm, ctx, tx)
	if err != nil {
		return nil, myerrors.NewByErr(err)
	}

	return r, nil
}

// Detail 按机构用户详情
func (p *mainService) Detail(mm *corestruct.IdModel, ctx *corestruct.HttpContext) (*data.HtRoleDto, error) {
	var qto = &coreqto.BasePageQto{
		Id:       mm.Id,
		Page:     1,
		PageSize: 1,
	}
	var r, err = p.Page(qto, ctx)
	if err != nil {
		return nil, err
	}
	if r.TotalRow == 0 {
		return nil, myerrors.NewDataNotExist()
	}
	var r1 = &r.Records[0]

	HtmenuIds, err := auth.GetRoleMenuIds(r1.Id, false, ctx)
	if err != nil {
		return nil, err
	}
	//特殊处理，不然int64 会失去精度
	var arr = make([]string, 0)
	for _, v := range *HtmenuIds {
		arr = append(arr, strconv.FormatInt(v, 10))
	}
	r1.HtmenuIds = &arr

	return r1, nil
}

// InsertInit 插入初始化
func (p *mainService) InsertInit(mm *corestruct.IdModel, ctx *corestruct.HttpContext) (*data.HtRoleDto, error) {
	arr := make([]string, 0)
	var r = &data.HtRoleDto{
		Id:   coreutil.IdUtil.GetId(),
		Name: "",

		Memo: "",

		CrtDt:  datetime.Now(),
		CrtUid: mm.Id,
		CrtDid: 0,

		CrtUname:  "",
		CrtDname:  "",
		HtmenuIds: &arr,
	}
	var db = ctx.DB
	r.CrtDname = coreservice.BaseService.GetName(&coreentity.HtDept{Id: r.CrtDid}, db)

	return r, nil
}

// CheckExistByEname
// 检查角色是不是存在
func (p *mainService) CheckExistByEname(name string, htplatId int64, ctx *corestruct.HttpContext) (bool, error) {
	var m = &coreentity.HtRole{Name: name}
	tx := ctx.DB.Where(m).
		Select("id").
		Where("htplat_id=?", htplatId).
		Find(m)
	if tx.Error != nil {
		return false, tx.Error
	}
	return m.Id > 0, nil
}

// Insert
// 插入用户
func (p *mainService) Insert(mm *data.HtRoleDto, ctx *corestruct.HttpContext) (int64, error) {
	bExist, err := p.CheckExistByEname(mm.Name, mm.HtplatId, ctx)
	if err != nil {
		return 0, myerrors.NewByErr(err)
	}
	if bExist == true {
		return 0, myerrors.New("角色名称重复")
	}

	var db = ctx.DB

	lrm := make([]coreentity.HtRoleMenu, 0)
	for _, v := range *mm.HtmenuIds {
		var mrm = &coreentity.HtRoleMenu{
			Id:       coreutil.IdUtil.GetId(),
			HtroleId: mm.Id,
			HtmenuId: int64(0),
		}
		mrm.HtmenuId, err = strconv.ParseInt(v, 10, 64)
		if err != nil {
			return 0, myerrors.NewByErr(err)
		}
		lrm = append(lrm, *mrm)
	}

	err = db.Transaction(func(tx *gorm.DB) error {

		for _, vrm := range lrm {
			tx2 := tx.Create(vrm)
			if tx2.Error != nil {
				return tx2.Error
			}
		}

		tx2 := coreservice.BaseService.InsertByDto(mm, &coreentity.HtRole{}, tx)
		if tx2.Error != nil {
			return tx2.Error
		}

		return nil
	})

	if err != nil {
		return 0, myerrors.NewByErr(err)
	}
	return mm.Id, nil
}

// Update
// 修改用户
func (p *mainService) Update(mm *data.HtRoleDto, ctx *corestruct.HttpContext) (int64, error) {
	var db = ctx.DB

	var m = &coreentity.HtRole{
		Id: mm.Id,
	}
	var err = db.Find(m).Error
	if err != nil {
		return 0, myerrors.NewByErr(err)
	}

	if m.Name != mm.Name {
		bExist, myerr := p.CheckExistByEname(mm.Name, mm.HtplatId, ctx)
		if myerr != nil {
			return 0, myerr
		}
		if bExist == true {
			return 0, myerrors.New("角色名称重复")
		}
	}

	HtmenuIds := make([]int64, 0)
	for _, v := range *mm.HtmenuIds {
		id, err := strconv.ParseInt(v, 10, 64)
		if err != nil {
			return 0, myerrors.NewByErr(err)
		}

		HtmenuIds = append(HtmenuIds, id)
	}
	var lrmold []int64
	err = db.Model(&coreentity.HtRoleMenu{}).
		Where("htrole_id=?", mm.Id).
		Select("htmenu_id").
		Find(&lrmold).Error
	if err != nil {
		return 0, myerrors.NewByErr(err)
	}
	var lidadd = coreutil.ArrayUtil.IdsNotIn(HtmenuIds, lrmold)
	var liddel = coreutil.ArrayUtil.IdsNotIn(lrmold, HtmenuIds)

	lrm := make([]coreentity.HtRoleMenu, 0)
	for _, v := range lidadd {
		var mrm = &coreentity.HtRoleMenu{
			Id:       coreutil.IdUtil.GetId(),
			HtroleId: mm.Id,
			HtmenuId: v,
		}
		lrm = append(lrm, *mrm)
	}

	err = db.Transaction(func(tx *gorm.DB) error {

		//添加新菜单
		for _, vrm := range lrm {
			tx2 := tx.Create(vrm)
			if tx2.Error != nil {
				return tx2.Error
			}
		}
		//删除菜单
		if len(liddel) > 0 {
			tx2 := tx.Delete(&coreentity.HtRoleMenu{}, "htrole_id=? and htmenu_id in ?", mm.Id, liddel)
			if tx2.Error != nil {
				return tx2.Error
			}
		}

		tx2 := coreservice.BaseService.UpdateByDto(mm, &coreentity.HtRole{Id: mm.Id}, tx)
		if tx2.Error != nil {
			return tx2.Error
		}
		if tx2.Error != nil {
			return tx2.Error
		}
		return nil
	})

	if err != nil {
		return 0, myerrors.NewByErr(err)
	}
	_ = coreservice.BaseService.DeleteCacheById(mm.Id)
	return mm.Id, nil
}

// ListByDeptId
// 根据dept获取role列表
func (p *mainService) ListByDeptId(mm *corestruct.IdModel, ctx *corestruct.HttpContext) (*[]corestruct.IdNameDto, error) {
	var db = ctx.DB
	var r []corestruct.IdNameDto
	var tx = db.Model(&coreentity.HtDept{}).
		InnerJoins(" inner join Htrole r on HtDept.id=? and HtDept.htplat_id=r.htplat_id", mm.Id).
		Select("r.id,r.name").
		Order("r.id").
		Find(&r)
	if tx.Error != nil {
		return nil, myerrors.NewByErr(tx.Error)
	}
	return &r, nil
}

var (
	MainService = &mainService{}
)
